import hashlib
import os
import json
from pathlib import Path
import folder_paths
from PIL import Image
from PIL.ExifTags import TAGS
from aiohttp import web
import aiohttp

import asyncio

try:
    import aiofiles
    from aiofiles import os as aio_os  # 异步os操作
except ImportError:
    raise ImportError("请安装aiofiles库: pip install aiofiles")

class ConfigService:
    default_config = {
        "sdwebuiPath": "http://127.0.0.1:7860/sdapi/",
        "url": "https://api.siliconflow.cn/v1/chat/completions",
        "model": "deepseek-ai/DeepSeek-V3",
        "baseUrl": "http://127.0.0.1:8188/",
        "comfyuiPath": "http://127.0.0.1:8188/",
        "comfyuiWsPath": "ws://127.0.0.1:8188/",
        "rate": 0.8,
        "scale": 0.4,
        "sdEngine": "comfyui",
        "baiduUrl": "https://fanyi-api.baidu.com/api/trans/vip/translate",
        "appid": "",
        "appkey": "",
        "salt": "kiki",
        "from": "en",
        "to": "zh",
        "loraPath": "E:\\AI\\SDWEBUI\\stable-diffusion-webui-master\\models\\Lora",
        "cachePath": "E:\\CivitaiCache\\",
        "imagesPath": "D:\\myBox\\images",
        "useNativeLoraLoader": True
    }

    @classmethod
    def _get_config_path(cls) -> str:
        """获取配置文件路径，位于插件根目录下"""
        current_dir = os.path.dirname(__file__)
        plugin_dir = os.path.abspath(os.path.join(current_dir, ".."))
        return os.path.join(plugin_dir, "config.json")

    @classmethod
    async def file_exists(cls, path: str) -> bool:
        """检查文件是否存在"""
        try:
            await aiofiles.open(path, mode='r')
            return True
        except FileNotFoundError:
            return False
        except Exception:
            return False

    @classmethod
    async def read_config(cls, request: web.Request) -> web.Response:  # 接收request参数
        """
        读取配置文件的aiohttp处理函数
        - 修复参数不匹配问题
        - 返回web.Response对象
        """
        try:
            config_path = cls._get_config_path()

            if not await cls.file_exists(config_path):
                # 不存在则创建并写入默认配置
                config_dir = os.path.dirname(config_path)
                if not await cls.file_exists(config_dir):
                    loop = asyncio.get_event_loop()
                    await loop.run_in_executor(
                        None,
                        lambda: os.makedirs(config_dir, exist_ok=True, mode=0o755)
                    )

                json_data = json.dumps(cls.default_config, indent=2, ensure_ascii=False)
                async with aiofiles.open(config_path, 'w', encoding='utf-8') as f:
                    await f.write(json_data)

                return web.json_response({
                    "success": True,
                    "data": cls.default_config.copy()
                })

            # 配置文件存在，读取并合并
            async with aiofiles.open(config_path, 'r', encoding='utf-8') as f:
                raw_data = await f.read()
                file_config = json.loads(raw_data)

            merged = {**cls.default_config, **file_config}
            return web.json_response({
                "success": True,
                "data": merged
            })
        except json.JSONDecodeError:
            error_msg = f"配置文件解析错误，使用默认配置"
            print(error_msg)
            return web.json_response({
                "success": False,
                "message": error_msg,
                "data": cls.default_config.copy()
            })
        except Exception as e:
            error_msg = f"读取配置文件失败: {str(e)}"
            print(error_msg)
            return web.json_response({
                "success": False,
                "message": error_msg,
                "data": cls.default_config.copy()
            })

    @classmethod
    async def save_config(cls, request: web.Request) -> web.Response:  # 接收request参数
        """
        保存配置文件的aiohttp处理函数
        - 修复参数不匹配问题
        - 从request中获取用户配置
        - 返回web.Response对象
        """
        try:
            # 从请求中获取用户配置
            user_config = await request.json()
            if not isinstance(user_config, dict):
                return web.json_response({
                    "success": False,
                    "message": "用户配置必须是字典类型"
                })

            config_path = cls._get_config_path()
            current_config = await cls._get_current_config()  # 使用内部方法获取当前配置

            # 合并优先级：用户配置 > 现有配置 > 默认配置
            final_config = {**current_config, **user_config}

            # 序列化配置
            json_data = json.dumps(final_config, indent=2, ensure_ascii=False)

            # 原子写入
            config_path_obj = Path(config_path)
            temp_file_name = f"{config_path_obj.name}.tmp-{os.urandom(8).hex()}"
            temp_path = config_path_obj.parent / temp_file_name

            try:
                loop = asyncio.get_event_loop()
                async with aiofiles.open(temp_path, 'w', encoding='utf-8') as f:
                    await f.write(json_data)
                    await loop.run_in_executor(None, lambda: os.fsync(f.fileno()))

                await loop.run_in_executor(
                    None,
                    lambda: os.replace(str(temp_path), str(config_path))
                )

                return web.json_response({
                    "success": True,
                    "message": "配置保存成功",
                    "data": final_config
                })
            except Exception as write_error:
                if await cls.file_exists(str(temp_path)):
                    try:
                        loop = asyncio.get_event_loop()
                        await loop.run_in_executor(None, lambda: os.unlink(str(temp_path)))
                    except Exception as cleanup_error:
                        print(f"清理临时文件失败: {str(cleanup_error)}")

                error_msg = f"保存配置文件失败: {str(write_error)}"
                print(error_msg)
                return web.json_response({
                    "success": False,
                    "message": error_msg
                })

        except Exception as e:
            error_msg = f"处理配置文件时发生错误: {str(e)}"
            print(error_msg)
            return web.json_response({
                "success": False,
                "message": error_msg
            })

    @classmethod
    async def _get_current_config(cls) -> dict:
        """内部方法：获取当前配置（不对外暴露为路由）"""
        config_path = cls._get_config_path()
        if await cls.file_exists(config_path):
            try:
                async with aiofiles.open(config_path, 'r', encoding='utf-8') as f:
                    raw_data = await f.read()
                    file_config = json.loads(raw_data)
                return {**cls.default_config, **file_config}
            except Exception:
                return cls.default_config.copy()
        return cls.default_config.copy()